package com.improvess.rna.som;

import Jama.Matrix;

import com.improvess.statistical.SOEM;

public class EMBasedProbabilisticSOM extends ProbabilisticSOM {

	private double limiarEM;
	private SOEM em;

	public EMBasedProbabilisticSOM(int quantidadeDeNeuronios,
			int quantidadeDeAtributos, double limiarEM,
			double sigmaVizinhancaInicial, double taxaDecrementoSigma, int quantidadeDeRegistros) {
		super(quantidadeDeNeuronios, quantidadeDeAtributos,
				sigmaVizinhancaInicial, quantidadeDeRegistros, taxaDecrementoSigma);
		this.limiarEM = limiarEM;
		inicializarNeuronios();
	}

	@Override
	public int aprendizagem(double[][] treinamento) {
		int tempo = 0;
		Matrix[] matrixTreinamento = new Matrix[treinamento.length];
		for (int i = 0; i < treinamento.length; i++) {
			double[] x = treinamento[i];
			matrixTreinamento[i] = new Matrix(new double[][] { x });
			matrixTreinamento[i] = matrixTreinamento[i].transpose();
		}
		NeuronioPb[][] neuronioPbs = new NeuronioPb[getNeuronios().length][];

		for (int i = 0; i < neuronioPbs.length; i++) {
			Neuronio[] neuronios = getNeuronios()[i];
			neuronioPbs[i] = new NeuronioPb[neuronios.length];
			for (int j = 0; j < neuronioPbs.length; j++) {
				neuronioPbs[i][j] = (NeuronioPb) neuronios[j];
			}
		}

		this.em = new SOEM(this.getQuantidadeDeAtributos(), matrixTreinamento,
				getLimiarEM(), getSigmaVizinhanca(), neuronioPbs);

		do {
			setNeuronios(em.process());
			em.setSigmaVizinhanca(em.getSigmaVizinhanca()- getTaxaDecrementoSigma());
			tempo++;
		} while (em.getSigmaVizinhanca() > 0);

		return tempo;
	}

	public double getLimiarEM() {
		return limiarEM;
	}

	public void setLimiarEM(double limiarEM) {
		this.limiarEM = limiarEM;
	}
	
}
